﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace CWCS.Common
{
    public class LED_UDP_Control
    {
        //#region 合肥项目
        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int SetScreenParameter(int nScreenNO, int nWidth, int nHeight, int nScreenType, int nMkType, int nDataDA, int nDataOE, int nDataStyle, int nDataSort, int nFrequency, byte* pFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int SetScreenTitle(int nX, int nY, int nWidth, int nHeight, int nScreenType, int nMkType,
        //byte* pFontName, int nFontSize, int nFontColor, int bBold, int bItalic, int bUnderLine, byte* pTitle,
        //int nStunt, int nRunSpeed, int nShowTime, byte* pFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int SetDynamicAttrib(int nX, int nY, int nWidth, int nHeight, int nScreenType, int nMkType,
        //    int bShowExceptPic, int nExceptTime, byte* pExceptPic, byte* pFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int TranDynamicData(int nScreenNO, int nOrdArea, int nX, int nY, int nWidth, int nHeight, int nScreenType,
        //int nMkType, int nPage, int nStunt, int nRunSpeed, int nShowTime, byte* pSourceName, int nSourceType,
        //byte* pDataFileName, int bDeleted);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int TranDynamicString(int nOrdArea, int nX, int nY, int nWidth, int nHeight, int nScreenType,
        //int nMkType, int nStunt, int nRunSpeed, int nShowTime, byte* pDynamicString, byte* pFontName, int FontSize,
        //int FontColor, int FontBold, byte* pDataFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int GetAllDataHead(int nScreenNO, int nProgramCount, byte* pFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int GetProgramHead(int nProgramOrd, int nAreaCount, int nProgPlayMode, int nProgPlayLength, int nProgWeekAttrib, int nPlayHour, int nPlayMinute, int nPlaySecond,
        //int nStopHour, int nStopMintue, int nStopSecond, byte* pFileName);


        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int GetCurDataTime(byte* pFileName);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int UnionAreaDataToFile(byte* pSourceFile, byte* pUnionedFile, int bDeleted);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int SendDataToComm(int nScreenNO, byte* pCom, int nBaud, int nSendType, int nWidth, int nHeight, int nScreenTpe, byte* pSendBufFile);

        //[DllImport("BxEDLL.dll", CallingConvention = CallingConvention.StdCall)]
        //public unsafe static extern int SendTCPIPData(byte* pTCPAddress, int nPort, int nSendType, int nWidth, int nHeight, int nScreenTpe, byte* pSendBufFile);
        //#endregion

        #region NetInitial
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_NetInitial(ushort nDevID, string Password, string RemoteIP, int SecTimeOut, int Retry, ushort UDPPort, bool bSCL2008);
        /// <summary>
        /// 创建Socket，并记录通讯中用到的超时、重试、控制器IP、控制器类型等参数。
        /// </summary>
        /// <param name="nDevID">由程序员给定的16位任意不同的设备编号。若初始化成功，对该设备调用通讯函数时必须使用相同的设备编号</param>
        /// <param name="Password">访问密码</param>
        /// <param name="RemoteIP">控制器的IP地址</param>
        /// <param name="SecTimeOut">通讯的延时阈值，时间超过该值尚未收到应答则认为通讯失败，单位：秒</param>
        /// <param name="Retry">通讯失败后的总的重试次数</param>
        /// <param name="UDPPort">建立UDP通讯使用的端口</param>
        /// <param name="bSCL2008"> TRUE表示控制器是SCL2008，FALSE表示控制器是SuperComm</param>
        /// <returns></returns>
        public bool NetInitial(ushort nDevID, string Password, string RemoteIP, int SecTimeOut, int Retry, ushort UDPPort, bool bSCL2008)
        {
            return SCL_NetInitial(nDevID, Password, RemoteIP, SecTimeOut, Retry, UDPPort, bSCL2008);
        }
        #endregion

        #region Close
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_Close(ushort nDevID);

        /// <summary>
        /// 关闭通讯，释放与编号相应的硬件资源
        /// </summary>
        /// <param name="nDevID">由程序员给定的16位任意不同的设备编号</param>
        /// <returns></returns>
        public bool Close(ushort nDevID)
        {
            return SCL_Close(nDevID);
        }
        #endregion

        #region struct TextOutInfo
        [StructLayout(LayoutKind.Sequential)]
        public struct TextOutInfo
        {
            public ushort Left;		// 区域左   , Left coordinate of the area.
            public ushort Top;		// 区域上   , Top  coordinate of the area.
            public ushort Width;		// 区域宽   , Width  of the area.
            public ushort Height;		// 区域高   , Height of the area.
            public long Color;		// 颜色     , Text color
            public ushort ASCFont;	// 英文字体 , Font index of ASCII charactors.
            public ushort HZFont;		// 中文字体 , Font index of Local language charactors.
            public ushort XPos;		// x坐标    , X coordinate for output text.
            public ushort YPos;		// y坐标    , Y coordinate for output text.
        };
        private static TextOutInfo textOut;
        #endregion

        #region ShowString
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_ShowString(ushort nDevID, ref TextOutInfo info, string str);

        public bool ShowString(ushort nDevID, ushort left, ushort top, ushort width, ushort height, long color, ushort aSCFont, ushort hZFont, ushort xPos, ushort yPos, string str)
        {
            textOut.Left = left;
            textOut.Top = top;
            textOut.Width = width;
            textOut.Height = height;
            textOut.Color = color;
            textOut.ASCFont = aSCFont;
            textOut.HZFont = hZFont;
            textOut.XPos = xPos;
            textOut.YPos = yPos;
            return SCL_ShowString(nDevID, ref textOut, str);
        }
        #endregion

        #region SendFile
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_SendFile(ushort nDevID, int drv, string Path, string LocalFileName);

        /// <summary>
        /// 将本地文件发送到控制器drv驱动器的Path目录下，文件名与计算机中的文件名一致。
        /// </summary>
        /// <param name="nDevID">设备编号</param>
        /// <param name="drv">驱动器编号,A盘是0，C盘是2</param>
        /// <param name="Path"> 控制器上的子目录，为空表示发送到根目录；若Path不为空，但该子目录不存在，则本函数返回FALSE</param>
        /// <param name="LocalFileName">本地文件名(含路径)，注意本地文件名必须符合8.3的格式，即不得使用长文件名。</param>
        /// <returns>发送成功，返回TRUE，否则返回FALSE</returns>
        public bool SendFile(ushort nDevID, int drv, string Path, string LocalFileName)
        {
            return SCL_SendFile(nDevID, drv, Path, LocalFileName);
        }
        #endregion

        #region RemoveFile
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_RemoveFile(ushort nDevID, int drv, string filename);
        /// <summary>
        /// 删除控制器上的某个文件
        /// </summary>
        /// <param name="nDevID"></param>
        /// <param name="drv"></param>
        /// <param name="filename">带路径的8.3格式的控制器上的文件名，如“P02\11.xmp”(子目录P02下的文件)，或“11.xmp”(根目录下的文件)</param>
        /// <returns></returns>
        public bool RemoveFile(ushort nDevID, int drv, string filename)
        {
            return SCL_RemoveFile(nDevID, drv, filename);
        }
        #endregion

        #region ReceiveFile
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern int SCL_ReceiveFile(ushort nDevID, int drv, string RemoteName, string LocalName);
        /// <summary>
        /// 将控制器上的文件取回到本地磁盘
        /// </summary>
        /// <param name="nDevID"></param>
        /// <param name="drv"></param>
        /// <param name="RemoteName">控制器上的文件名，如“P02\11.xmp”(子目录P02下的文件)，或“11.xmp”(根目录下的文件)；</param>
        /// <param name="LocalName">本地文件名(含路径)</param>
        /// <returns>取回文件成功，返回文件长度，否则返回-1</returns>
        public int ReceiveFile(ushort nDevID, int drv, string RemoteName, string LocalName)
        {
            return SCL_ReceiveFile(nDevID, drv, RemoteName, LocalName);
        }
        #endregion

        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_GetFileDosDateTime(string FileName, ref int Date, ref int Time);

        #region PLayList_Replay
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_Replay(ushort nDevID, int drv, int Index);

        /// <summary>
        /// 当全部图片及节目表文件都发送到控制器上后，调用此函数令控制器执行新节目表
        /// </summary>
        /// <param name="nDevID"></param>
        /// <param name="drv">驱动器编号,A盘是0，C盘是2</param>
        /// <param name="Index">节目表编号，0-99。例如，SCL_Replay(nDevID,2,8)可命令控制器播放C:\P08目录下的PLAYLIST.LY；SCL_Replay(nDevID,1,3)则命令控制器播放B:\P03目录下的节目表PLAYLIST.LY</param>
        /// <returns>若控制器开始播放新节目表，返回TRUE，否则返回FALSE</returns>
        public bool Replay(ushort nDevID, int drv, int Index)
        {
            return SCL_Replay(nDevID, drv, Index);
        }
        #endregion

        #region CreateFolder
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_MD(ushort nDevID, int drv, string path);

        /// <summary>
        /// 在某驱动器的根目录下创建一个子目录
        /// </summary>
        /// <param name="nDevID"></param>
        /// <param name="drv"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool CreateFolder(ushort nDevID, int drv, string path)
        {
            return SCL_MD(nDevID, drv, path);
        }
        #endregion

        #region Reset
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_Reset(ushort nDevID);
        /// <summary>
        /// 复位控制器
        /// </summary>
        /// <param name="nDevID"></param>
        /// <returns></returns>
        public bool Reset(ushort nDevID)
        { return SCL_Reset(nDevID); }
        #endregion

        #region SetOnOffTime
        [DllImport("SCL_API_stdcall.Dll")]
        private static extern bool SCL_SetOnOffTime(ushort nDevID, ushort OnTime, ushort OffTime);
        /// <summary>
        /// 设置自动开关屏时间。重新上电后可能需要强行打开显示屏。
        /// 若需要强行关闭显示屏，可设置开屏时间、关屏时间均为0；
        /// 若需强行打开显示屏，可设置开屏时间和关屏时间均为23点59分.
        /// OnTime和OffTime的格式为 时*100+分。例如，9点28分将写成928
        /// </summary>
        /// <param name="nDevID">设备编号</param>
        /// <param name="OnTime">开屏时间</param>
        /// <param name="OffTime">关屏时间</param>
        /// <returns></returns>
        public bool SetOnOffTime(ushort nDevID, ushort OnTime, ushort OffTime)
        {
            return SCL_SetOnOffTime(nDevID, OnTime, OffTime);
        }
        #endregion

        /// <summary>
        ///  把str2show写到文本里面，然后发送到控制器的C盘，发送成功后重启节目表。发送文件的重试次数为NTimes
        /// </summary>
        /// <param name="nDevID"></param>
        /// <param name="str2show"></param>
        /// <param name="LocalTempFileName">作为暂存的。一开始往里面写入信息，然后发送文件。</param>
        /// <param name="NTimes"></param>
        /// <param name="Index"></param>
        /// <returns></returns>
        public bool SendStringNtimes(ushort nDevID, string str2show, string LocalTempFileName, int NTimes, int Index)
        {

            File.WriteAllText(LocalTempFileName, "`R0000000001600032`A1`H2`C0000FF " + str2show, Encoding.GetEncoding("gb2312"));
            for (int j = 0; j < NTimes; j++)
            {
                if (SendFile(nDevID, 2, "", LocalTempFileName))//把LocalTempFile发送到C盘，失败则休眠一段时间再发送
                {
                    if (Replay(nDevID, 0, Index)) //发送成功后重启节目单
                        return true;//如果成功返回ture
                    else
                        return false;
                }
                System.Threading.Thread.Sleep(1000);//休眠一段时间进入下次发送
            }
            return false;
        }

       
    }
}
